package org.example.myleet.p707;

public class MyLinkedList {

    private static class Node {
        int val;
        Node next;

        public Node(int val) {
            this.val = val;
            this.next = null;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("Node{");
            sb.append("val=").append(val);
            sb.append('}');
            return sb.toString();
        }
    }

    private final Node dummyHead;

    /**
     * 链表大学
     */
    private int size;

    /**
     * 链表游标，缓存上一个读取或处理链表的位置
     */
    private int curIndex;

    /**
     * 链表游标，缓存上一个读取或处理链表的位置
     */
    private Node cur;

    public MyLinkedList() {
        dummyHead = new Node(-1);
        size = 0;
        curIndex = -1;
        cur = dummyHead;
    }

    public int get(int index) {
        if (index > size - 1 || index < 0) {
            return -1;
        }
        if (index < curIndex) {
            curIndex = -1;
            cur = dummyHead;
        }
        while (curIndex != index) {
            ++curIndex;
            cur = cur.next;
        }
        return cur.val;
    }

    public void addAtHead(int val) {
        Node next = dummyHead.next;
        dummyHead.next = new Node(val);
        dummyHead.next.next = next;
        if (curIndex > -1) {
            ++curIndex;
        }
        ++size;
    }

    public void addAtTail(int val) {
        if (size == 0) {
            addAtHead(val);
            return;
        }
        get(size - 1);
        cur.next = new Node(val);
        ++size;
    }

    public void addAtIndex(int index, int val) {
        if (index > size || index < 0) {
            return;
        }
        if (index == 0) {
            addAtHead(val);
            return;
        }
        get(index - 1);
        Node next = cur.next;
        cur.next = new Node(val);
        cur.next.next = next;
        ++size;
    }

    public void deleteAtIndex(int index) {
        if (index > size - 1 || index < 0 || size == 0) {
            return;
        }
        if (index == 0) {
            Node next = dummyHead.next;
            dummyHead.next = next.next;
        } else {
            get(index - 1);
            Node next = cur.next;
            cur.next = next.next;
        }
        --size;
    }
}
